class Tetris {
  constructor() {
    this.boardWidth = 10;
    this.boardHeight = 20;
    this.board = Array(this.boardHeight)
      .fill()
      .map(() => Array(this.boardWidth).fill(0));
    this.score = 0;
    this.gameOver = false;
    this.isPaused = false;
    this.currentPiece = null;
    this.nextPiece = null;

    // 方块形状定义
    this.shapes = {
      I: [[1, 1, 1, 1]],
      O: [
        [1, 1],
        [1, 1],
      ],
      T: [
        [0, 1, 0],
        [1, 1, 1],
      ],
      S: [
        [0, 1, 1],
        [1, 1, 0],
      ],
      Z: [
        [1, 1, 0],
        [0, 1, 1],
      ],
      J: [
        [1, 0, 0],
        [1, 1, 1],
      ],
      L: [
        [0, 0, 1],
        [1, 1, 1],
      ],
    };

    this.init();
  }

  init() {
    this.gameBoard = document.getElementById("game-board");
    this.nextPieceDisplay = document.getElementById("next-piece-display");
    this.scoreDisplay = document.getElementById("score");
    this.startButton = document.getElementById("start-btn");

    // 初始化游戏板
    this.createBoard();
    this.createNextPieceDisplay();

    // 绑定事件
    this.startButton.addEventListener("click", () => this.startGame());
    document.addEventListener("keydown", (e) => this.handleKeyPress(e));
  }

  createBoard() {
    this.gameBoard.innerHTML = "";
    for (let i = 0; i < this.boardHeight; i++) {
      for (let j = 0; j < this.boardWidth; j++) {
        const cell = document.createElement("div");
        cell.className = "cell";
        this.gameBoard.appendChild(cell);
      }
    }
  }

  createNextPieceDisplay() {
    this.nextPieceDisplay.innerHTML = "";
    for (let i = 0; i < 4; i++) {
      for (let j = 0; j < 4; j++) {
        const cell = document.createElement("div");
        cell.className = "cell";
        this.nextPieceDisplay.appendChild(cell);
      }
    }
  }

  startGame() {
    this.board = Array(this.boardHeight)
      .fill()
      .map(() => Array(this.boardWidth).fill(0));
    this.score = 0;
    this.gameOver = false;
    this.isPaused = false;
    this.updateScore();
    this.createBoard();

    if (!this.currentPiece) {
      this.currentPiece = this.generatePiece();
      this.nextPiece = this.generatePiece();
    }

    if (!this.gameInterval) {
      this.gameInterval = setInterval(() => this.gameLoop(), 1000);
    }

    this.startButton.textContent = "重新开始";
    this.render();
  }

  generatePiece() {
    const pieces = Object.keys(this.shapes);
    const type = pieces[Math.floor(Math.random() * pieces.length)];
    const shape = this.shapes[type];
    return {
      type,
      shape: JSON.parse(JSON.stringify(shape)),
      x: Math.floor((this.boardWidth - shape[0].length) / 2),
      y: 0,
    };
  }

  gameLoop() {
    if (this.gameOver || this.isPaused) return;
    if (!this.moveDown()) {
      this.placePiece();
      this.clearLines();
      this.currentPiece = this.nextPiece;
      this.nextPiece = this.generatePiece();

      if (this.checkCollision(this.currentPiece)) {
        this.gameOver = true;
        clearInterval(this.gameInterval);
        this.gameInterval = null;
        alert("游戏结束！得分：" + this.score);
        return;
      }
    }
    this.render();
  }

  moveDown() {
    this.currentPiece.y++;
    if (this.checkCollision(this.currentPiece)) {
      this.currentPiece.y--;
      return false;
    }
    return true;
  }

  moveLeft() {
    this.currentPiece.x--;
    if (this.checkCollision(this.currentPiece)) {
      this.currentPiece.x++;
      return false;
    }
    this.render();
    return true;
  }

  moveRight() {
    this.currentPiece.x++;
    if (this.checkCollision(this.currentPiece)) {
      this.currentPiece.x--;
      return false;
    }
    this.render();
    return true;
  }

  rotate() {
    const oldShape = this.currentPiece.shape;
    const rotated = oldShape[0].map((_, i) =>
      oldShape.map((row) => row[i]).reverse()
    );
    this.currentPiece.shape = rotated;

    if (this.checkCollision(this.currentPiece)) {
      this.currentPiece.shape = oldShape;
      return false;
    }
    this.render();
    return true;
  }

  checkCollision(piece) {
    return piece.shape.some((row, dy) =>
      row.some((value, dx) => {
        if (!value) return false;
        const newX = piece.x + dx;
        const newY = piece.y + dy;
        return (
          newX < 0 ||
          newX >= this.boardWidth ||
          newY >= this.boardHeight ||
          (newY >= 0 && this.board[newY][newX])
        );
      })
    );
  }

  placePiece() {
    this.currentPiece.shape.forEach((row, dy) => {
      row.forEach((value, dx) => {
        if (value) {
          const newY = this.currentPiece.y + dy;
          const newX = this.currentPiece.x + dx;
          if (newY >= 0) {
            this.board[newY][newX] = this.currentPiece.type;
          }
        }
      });
    });
  }

  clearLines() {
    let linesCleared = 0;
    for (let y = this.boardHeight - 1; y >= 0; y--) {
      if (this.board[y].every((cell) => cell)) {
        this.board.splice(y, 1);
        this.board.unshift(Array(this.boardWidth).fill(0));
        linesCleared++;
        y++;
      }
    }
    if (linesCleared > 0) {
      this.score += linesCleared * 100;
      this.updateScore();
    }
  }

  updateScore() {
    this.scoreDisplay.textContent = this.score;
  }

  render() {
    // 清空游戏板
    const cells = this.gameBoard.getElementsByClassName("cell");
    let index = 0;

    // 渲染已固定的方块
    for (let y = 0; y < this.boardHeight; y++) {
      for (let x = 0; x < this.boardWidth; x++) {
        cells[index].className = "cell";
        if (this.board[y][x]) {
          cells[index].classList.add("filled");
          cells[index].classList.add(`piece-${this.board[y][x]}`);
        }
        index++;
      }
    }

    // 渲染当前方块
    if (this.currentPiece) {
      this.currentPiece.shape.forEach((row, dy) => {
        row.forEach((value, dx) => {
          if (value) {
            const y = this.currentPiece.y + dy;
            const x = this.currentPiece.x + dx;
            if (
              y >= 0 &&
              y < this.boardHeight &&
              x >= 0 &&
              x < this.boardWidth
            ) {
              const cellIndex = y * this.boardWidth + x;
              cells[cellIndex].classList.add("filled");
              cells[cellIndex].classList.add(`piece-${this.currentPiece.type}`);
            }
          }
        });
      });
    }

    // 渲染下一个方块
    const nextPieceCells = this.nextPieceDisplay.getElementsByClassName("cell");
    Array.from(nextPieceCells).forEach((cell) => (cell.className = "cell"));

    if (this.nextPiece) {
      const offsetX = Math.floor((4 - this.nextPiece.shape[0].length) / 2);
      const offsetY = Math.floor((4 - this.nextPiece.shape.length) / 2);

      this.nextPiece.shape.forEach((row, dy) => {
        row.forEach((value, dx) => {
          if (value) {
            const cellIndex = (dy + offsetY) * 4 + (dx + offsetX);
            nextPieceCells[cellIndex].classList.add("filled");
            nextPieceCells[cellIndex].classList.add(
              `piece-${this.nextPiece.type}`
            );
          }
        });
      });
    }
  }

  handleKeyPress(event) {
    if (this.gameOver) return;

    switch (event.key) {
      case "ArrowLeft":
        this.moveLeft();
        break;
      case "ArrowRight":
        this.moveRight();
        break;
      case "ArrowUp":
        this.rotate();
        break;
      case "ArrowDown":
        this.moveDown();
        break;
      case " ":
        while (this.moveDown()) {}
        break;
      case "p":
      case "P":
        this.isPaused = !this.isPaused;
        break;
    }
  }
}

// 初始化游戏
window.addEventListener("load", () => {
  new Tetris();
});
